package service

import (
	"context"
	"encoding/json"
	"k8s-dash/dto"
	"k8s-dash/utils"
	coreV1 "k8s.io/api/core/v1"
	metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
)

type service struct{}

var Service service

type SVCeResp struct {
	Total int              `json:"total"`
	Items []coreV1.Service `json:"items"`
}

type serviceNp struct {
	NameSpace  string `json:"namespace"`
	ServiceNum int    `json:"service_num"`
}

// GetSVCList 获取svc列表
func (s *service) GetSVCList(filterName, namespace string, limit, page int) (ss *SVCeResp, err error) {
	svcList, err := utils.K8sClient.K8sClient.CoreV1().Services(namespace).List(context.TODO(), metaV1.ListOptions{})
	if err != nil {
		return nil, err
	}
	//封装数据
	selectData := &dataSelector{
		GenericDataList: s.toCells(svcList.Items),
		DataSelectQuery: &DataSelectorQuery{
			Filter: &FilterQuery{filterName},
			Paginate: &PageQuery{
				Limit: limit,
				Page:  page,
			},
		},
	}
	data := selectData.Filter()
	total := len(data.GenericDataList)
	cells := data.Sort().Paginate()
	nss := s.FromCells(cells.GenericDataList)
	return &SVCeResp{
		Total: total,
		Items: nss,
	}, nil
}

// GetSVCDetail 获取svc详情
func (s *service) GetSVCDetail(namespace, name string) (*coreV1.Service, error) {
	svc, err := utils.K8sClient.K8sClient.CoreV1().Services(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
	if err != nil {
		return nil, err
	}
	return svc, nil
}

// DeleteSVC  删除svc
func (s *service) DeleteSVC(namespace, name string) error {
	err := utils.K8sClient.K8sClient.CoreV1().Services(namespace).Delete(context.TODO(), name, metaV1.DeleteOptions{})
	if err != nil {
		return err
	}
	return nil
}

// CreateSVC 创建service
func (s *service) CreateSVC(data *dto.ServiceCreateInput) error {
	var svc = &coreV1.Service{
		ObjectMeta: metaV1.ObjectMeta{
			Name:      data.Name,
			Labels:    data.Label,
			Namespace: data.NameSpace,
		},
		Spec: coreV1.ServiceSpec{
			Type: coreV1.ServiceType(data.Type),
			Ports: []coreV1.ServicePort{
				{
					Port:     data.Port,
					Name:     "http",
					Protocol: "TCP",
					TargetPort: intstr.IntOrString{
						Type:   0,
						IntVal: data.ContainerPort,
					},
				},
			},
			Selector: data.Label,
		},
		Status: coreV1.ServiceStatus{},
	}
	if data.NodePort != 0 && data.Type != "NodePort" {
		svc.Spec.Ports[0].NodePort = data.NodePort
	}
	_, err := utils.K8sClient.K8sClient.CoreV1().Services(data.NameSpace).Create(context.TODO(), svc, metaV1.CreateOptions{})
	if err != nil {
		return err
	}
	return nil
}

// UpdateSVC 更新svc
func (s *service) UpdateSVC(namespace, content string) error {
	var svc = &coreV1.Service{}
	err := json.Unmarshal([]byte(content), svc)
	if err != nil {
		return err
	}
	if _, err := utils.K8sClient.K8sClient.CoreV1().Services(namespace).Update(context.TODO(), svc, metaV1.UpdateOptions{}); err != nil {
		return err
	}
	return nil
}

// GetSVCNP 获取各个ns下svc的数量
func (s *service) GetSVCNP() ([]*serviceNp, error) {
	namespaceList, err := utils.K8sClient.K8sClient.CoreV1().Namespaces().List(context.TODO(), metaV1.ListOptions{})
	if err != nil {
		return nil, err
	}
	var services []*serviceNp
	for _, ns := range namespaceList.Items {
		serviceList, err := utils.K8sClient.K8sClient.CoreV1().Services(ns.Name).List(context.TODO(), metaV1.ListOptions{})
		if err != nil {
			return nil, err
		}
		//封装数据
		snp := &serviceNp{
			NameSpace:  ns.Name,
			ServiceNum: len(serviceList.Items),
		}
		services = append(services, snp)
	}
	return services, nil
}

// 类型转换的方法 coreV1.service => DataCell,DataCell => coreV1.service
func (p *service) toCells(nodes []coreV1.Service) []DataCell {
	cells := make([]DataCell, len(nodes))
	for i := range nodes {
		cells[i] = svcCell(nodes[i])
	}
	return cells
}

func (p *service) FromCells(cells []DataCell) []coreV1.Service {
	nodes := make([]coreV1.Service, len(cells))
	for i := range cells {
		nodes[i] = coreV1.Service(cells[i].(svcCell))
	}
	return nodes
}
